top.tools = {
    file: () => {
        let _options = {
            elem: undefined,
            url: top.tools.getBaseUrl() + '/file/upload', // 此处配置你自己的上传接口即可
            headers: {
                'Access-Token': top.tools.cookie.token(),
                // 'Content-Type':'multipart/form-data',
            },
            size: undefined, // 限制文件大小，单位 KB
            dataType: undefined,
            accept: undefined,
            acceptMime: undefined,
            exts: undefined,
            auto: undefined,
            bindAction: undefined,
            multiple: undefined,
            unified: undefined,
            number: undefined,
            drag: undefined,
            choose: undefined,
            before: undefined,
            progress: undefined,
            done: undefined,
            allDone: undefined,
            error: undefined,
        }

        function uploadFile(options) {
            optionsBefore(options);
            return upload.render({..._options, ...options});
        }

        function uploadFiles(options) {
            optionsBefore(options);
            _options.fieId = "files"
            _options.url = top.tools.getBaseUrl() + '/file/uploads';
            return upload.render({..._options, ...options});
        }

        function optionsBefore(options) {
            _options.before = function (obj) {
                //layui-icon-loading
                $(options.elem).find("i").attr("class", "layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop");
            }
            _options.error = function (index, upload, res, xhr) {
                // console.log(res);
                $(options.elem).html('<i class="layui-icon layui-icon-close-circle"></i>')
            }
        }

        function downloadFile(options) {
            if (!options.avatar) {
                return;
            }
            $(options.elem).html('<i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop" </i>')
            fetch(top.tools.getBaseUrl() + '/file/download/' + options.avatar, {
                method: "POST",
                headers: {
                    "Access-Token": top.tools.cookie.token(),
                    'Content-Type': 'application/json;charset=UTF-8'
                },
            }).then(function (response) {
                return response.blob();
            }).then(function (blob) {
                var url = URL.createObjectURL(blob);
                $(options.elem).html('<img src="' + url + '" alt="">');
            }).catch(function () {
                $(options.elem).html('<i class="layui-icon layui-icon-close-circle" </i>')
            })
        }

        return {uploadFile, uploadFiles, downloadFile};
    },
    cache: {
        dictMap: {},
        getUser: function () {
            return layui.data('user');
        },
        setUser: function (user) {
            user.password = "********";
            user.mobile = user.mobile.substr(0, 3) + "****" + user.mobile.substr(7);
            this.set('user', user);
        },
        getResources: function () {
            return layui.data('resources');
        },
        setResources: function (resources) {
            this.set('resources', resources);
        },
        set: function (key, value) {
            if (typeof value === 'string') {
                layui.data(key, {key: key, value: value});
            } else if (typeof value === 'object') {
                layui.each(value, function (k, v) {
                    layui.data(key, {key: k, value: v});
                })
            }
        },
        get: function (key) {
            return layui.data(key)
        },
        remove: function (key) {
            layui.data(key, null);
        },
        logoutRemove: function () {
            layui.data('user', null);
            layui.data('resources', null);
        }
    },
    dict: () => {
        function getDictByType(dictType) {
            if (top.tools.cache.dictMap[dictType] && top.tools.cache.dictMap[dictType].length > 0) {
                return top.tools.cache.dictMap[dictType];
            }
            let dictData = undefined;
            top.tools.ajax({
                url: '/common/getDataByDictType',
                loading: false,
                async: false,
                type: 'post',
                data: {dictType: dictType},
                dataType: 'json',
                beforeSendFun: function (xhr) {
                    if (top.tools.cache.dictMap[dictType] && top.tools.cache.dictMap[dictType].length > 0) {
                        xhr.abort();
                        dictData = top.tools.cache.dictMap[dictType];
                    }
                },
                successFun: function (response) {
                    if (response.code === 200) {
                        top.tools.cache.dictMap[dictType] = response.data;
                        dictData = top.tools.cache.dictMap[dictType];
                    }
                },
            })
            return dictData;
        }

        function getDictLabel(dictType, dictValue) {
            let dict = undefined;
            if (top.tools.cache.dictMap[dictType] && top.tools.cache.dictMap[dictType].length > 0) {
                dict = top.tools.cache.dictMap[dictType];
            }
            if (!dict) {
                dict = getDictByType(dictType)
            }

            let label = '';
            layui.each(dict, function (index, item) {
                if (item.value == dictValue) {
                    label = item.label;
                }
            })
            return label;
        }

        return {getDictByType, getDictLabel}
    },
    message: {
        // 更新页面显示
        update: function (count) {
            if (count > 0) {
                $('a[lay-header-event=message] .layui-badge-dot').removeClass('layui-hide');
            } else {
                $('a[lay-header-event=message] .layui-badge-dot').addClass('layui-hide');
            }
        }
    },
    theme: {
        setTheme: function (theme) {
            if (!theme) {
                return
            }
            var
                l = "LAY_layadmin_theme",
                s = document.createElement("style"),
                r = laytpl([".layui-side-menu,", ".layadmin-pagetabs .layui-tab-title li:after,", ".layadmin-pagetabs .layui-tab-title li.layui-this:after,", ".layui-layer-admin .layui-layer-title,", ".layadmin-side-shrink .layui-side-menu .layui-nav>.layui-nav-item>.layui-nav-child", "{background-color:{{d.color.main}} !important;}", ".layui-nav-tree .layui-this,", ".layui-nav-tree .layui-this>a,", ".layui-nav-tree .layui-nav-child dd.layui-this,", ".layui-nav-tree .layui-nav-child dd.layui-this a", "{background-color:{{d.color.selected}} !important;}", ".layui-layout-admin .layui-logo{background-color:{{d.color.logo || d.color.main}} !important;}", "{{# if(d.color.header){ }}", ".layui-layout-admin .layui-header{background-color:{{ d.color.header }};}", ".layui-layout-admin .layui-header a,", ".layui-layout-admin .layui-header a cite{color: #f8f8f8;}", ".layui-layout-admin .layui-header a:hover{color: #fff;}", ".layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #fbfbfb;}", ".layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #fbfbfb;}", ".layui-layout-admin .layui-header .layui-nav .layui-this:after, .layui-layout-admin .layui-header .layui-nav-bar{background-color: #fff; background-color: rgba(255,255,255,.5);}", ".layadmin-pagetabs .layui-tab-title li:after{display: none;}", "{{# } }}"]
                    .join("")).render({color: theme}),
                u = document.getElementById(l);
            "styleSheet" in s ? (s.setAttribute("type", "text/css"), s.styleSheet.cssText = r) : s.innerHTML = r;
            s.id = l;
            if (u) {
                $("body")[0].removeChild(u)
            }
            $("body")[0].appendChild(s);
            $("body").attr("layadmin-themealias", theme.alias);
            layui.data('layui_theme', {key: 'color', value: theme})
        },
        initTheme: function (index) {
            var themeList = top.config.theme.color;
            index = index || 0;
            themeList[index] && (themeList[index].index = index, top.tools.theme.setTheme(themeList[index]))
        },
    },
    ajax(options) {
        /*
        *  options:
        *    url:请求路径(不包含基础路径)
        *    loading:是否显示
        *    type:请求类型
        *    data:请求数据
        *    dataType:返回类型
        *    beforeSendFun:请求之前回调
        *    successFun:成功时回调
        *    errorFun:失败时回调
        * */
        options.url = top.tools.getBaseUrl() + options.url;
        if (typeof options.loading !== 'boolean' || options.loading !== false) {
            options.loading = true;
        }

        if ((options.type === 'post' || options.type === 'POST') && typeof options.data !== 'string') {
            options.data = JSON.stringify(options.data)
            options.contentType = 'application/json'
        }

        options.beforeSend = function (xhr) {
            if (options.beforeSendFun && typeof options.beforeSendFun === 'function') {
                options.beforeSendFun(xhr)
            }

            xhr.setRequestHeader("Access-Token", top.tools.cookie.token());
            //显示加载动画
            if (options.loading) {
                if (activeRequests === 0){
                    top.tools.loading();
                }
                activeRequests++;
            }
        }
        options.complete = function (xhr, status) {
            if (options.loading) {
                activeRequests--;
                if (activeRequests === 0){
                    layui.layer.close(loadingId);
                }
            }
        }

        options.success = function (response, status, xhr) {
            if (typeof response === "string") {
                try {
                    response = JSON.parse(response)
                    if (response.code && response.code === 10001) {
                        top.tools.cache.logoutRemove();
                        window.location.href = window.location.origin + system_config.basePath + "/?message=" + response.message;
                        return;
                    }
                } catch (e) {
                }
            }
            if (response.code && response.code === 10001) {
                top.tools.cache.logoutRemove();
                window.location.href = window.location.origin + system_config.basePath + "/?message=" + response.message;
                return;
            }
            if (options.dataType === 'json') {
                if (response.code === 200) {
                    if (options.successFun && typeof options.successFun === 'function') {
                        options.successFun(response, status, xhr)
                    }
                } else {
                    layer.msg(response.message, {icon: 2}, function () {
                        // layer.msg('提示框关闭后的回调');
                    });
                    if (options.errorFun && typeof options.errorFun === 'function') {
                        options.errorFun(response)
                    }
                }
            } else {
                if (options.successFun && typeof options.successFun === 'function') {
                    options.successFun(response, status, xhr)
                }
            }

        }

        options.error = function (xhr, textStatus, errorThrown) {
            if (options.errorFun && typeof options.errorFun === 'function') {
                options.errorFun(xhr, textStatus, errorThrown)
            }
        }
        layui.$.ajax(options)
    },
    crypto:{
        MD5:function (data){
            return CryptoJS.MD5(data).toString();
        },
        SHA1:function (data){
            return CryptoJS.SHA1(data).toString();
        },
        SHA256:function (data){
            return CryptoJS.SHA256(data).toString();
        },
        SHA512:function (data){
            return CryptoJS.SHA512(data).toString();
        },
        SHA3:function (data){
            return CryptoJS.SHA3(data).toString();
        },
        AES:{
            encrypt: function (data, key) {
                return CryptoJS.AES.encrypt(data, key).toString()
            },
            decrypt:function (data, key){
                var bytes  = CryptoJS.AES.decrypt(data, key);
                return bytes.toString(CryptoJS.enc.Utf8);
            }
        },
        SM2:{
            encrypt: function (data, publicKey) {
                return sm2.doEncrypt(data, publicKey || top.config.constant.sm2.publicKey)
            },
            decrypt:function (data, privateKey){
                return sm2.doDecrypt(data, privateKey || top.config.constant.sm2.privateKey)
            },
            signa:function (data, privateKey){
                return sm2.doSignature(data, privateKey || top.config.constant.sm2.privateKey); // 签名
            },
            verifySigna:function (signa,data, publicKey){
                return sm2.doVerifySignature(data, signa, publicKey || top.config.constant.sm2.publicKey);
            }
        },
        SM3:function (data,key) {
            return sm3(data,key || top.config.constant.sm3)
        },
        SM4:{
            encrypt: function (data, key) {
                return sm4.encrypt(data, key || top.config.constant.sm4.key)
            },
            decrypt:function (data, key){
                return sm4.decrypt(data, key || top.config.constant.sm4.key)
            },
        },
        SM4_CBC:{
            encrypt: function (data, key,iv) {
                return sm4.encrypt(data, key || top.config.constant.sm4.key,{mode: 'cbc', iv: iv || top.config.constant.sm4.iv})
            },
            decrypt:function (data, key,iv){
                return sm4.decrypt(data, key || top.config.constant.sm4.key,{mode: 'cbc', iv: iv || top.config.constant.sm4.iv})
            },
        }
    },
    cookie: {
        set: function (name, value) {
            Cookies.set(name, value, {path: '/'});
        },
        get: function (name) {
            return Cookies.get(name);
        },
        remove: function (name) {
            Cookies.remove(name);
        },
        token: function () {
            return Cookies.get(top.config.constant.token)
        },
        removeToken: function () {
            return Cookies.remove(top.config.constant.token)
        }
    },
    loading: function () {
        loadingId = layui.layer.open({
            type: 3, // page 层类型
            shade: [0.5, '#FFF'], // 遮罩透明度
            icon: 2,
            anim: 0, // 0-6 的动画形式，-1 不开启
            content: '<div class="">加载中</div>'
        });
    },
    getBaseUrl: function () {
        return system_config.basePath + system_config.apiBaseUrl;
    },
    form: {
        getFindElementOnObj: function (element = "search-criteria", isVal = true) {
            // 创建一个空对象来存储结果
            let result = {};

            // 获取所有input和select元素
            $(element).find('input, select,textarea').each(function () {
                // 获取元素的name属性
                const name = $(this).attr('name');
                // 跳过没有name的元素
                if (!name) return;
                if (isVal) {
                    if (!form.validate($(this))) {
                        result = false;
                        return false;
                    }
                }

                let value = $(this).val();

                // 单选和多选框特殊处理，只处理选中的
                if (this.type === 'radio' || this.type === 'checkbox') {
                    // 只有选中的元素才有value
                    if (this.checked) {
                        value = this.value;
                    } else {
                        return; // 未选中的单选或多选框不添加到结果中
                    }
                }

                // 如果是多选，确保value是数组
                if (this.type === 'select-multiple') {
                    value = $(this).find('option:selected').map(function () {
                        return this.value;
                    }).get();
                }

                // 如果name已经存在于结果对象中，则合并值
                if (result[name]) {
                    // 如果已经是数组，则直接添加value
                    if (Array.isArray(result[name])) {
                        result[name].push(value);
                    } else {
                        // 否则将当前值转为数组，并添加新值
                        result[name] = [result[name], value];
                    }
                } else {
                    // 如果name不存在于结果对象中，则直接设置值
                    result[name] = value;
                }
                if (!isVal) {
                    result[name] = "";
                }
            });

            return result;
        },
        formatDate: function (date, type = "yyyy-MM-dd HH:mm:ss") {
            if (!date) {
                return '';
            }
            let dateObj = new Date(date);
            let year = dateObj.getFullYear();
            let month = String(dateObj.getMonth() + 1).padStart(2, '0');
            let day = String(dateObj.getDate()).padStart(2, '0');
            let hours = String(dateObj.getHours()).padStart(2, '0');
            let minutes = String(dateObj.getMinutes()).padStart(2, '0');
            let seconds = String(dateObj.getSeconds()).padStart(2, '0');
            if (type === "yyyy-MM-dd HH:mm:ss") {
                return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
            }
            if (type === "yyyy-MM-dd") {
                return `${year}-${month}-${day}`;
            }
        },
        generatePassword: function () {
            const characters = {
                digits: "0123456789",
                lowercase: "abcdefghijklmnopqrstuvwxyz",
                uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                special: "!@#$%^&*()_+-=[]{}|;':\",./<>?"
            };

            // 用于记录已选用的字符类型数量
            let typesCount = 0;
            let password = "";

            // 确保至少选择三种字符类型来构建密码
            const selectedTypes = [];
            while (typesCount < 3) {
                const randomType = Object.keys(characters)[Math.floor(Math.random() * Object.keys(characters).length)];
                if (!selectedTypes.includes(randomType)) {
                    selectedTypes.push(randomType);
                    typesCount++;
                }
            }

            // 根据选定的字符类型生成一定长度的密码
            const targetLength = Math.floor(Math.random() * 13 + 8); // 生成8到20位之间的长度
            while (password.length < targetLength) {
                const randomSelectedType = selectedTypes[Math.floor(Math.random() * selectedTypes.length)];
                const randomChar = characters[randomSelectedType][Math.floor(Math.random() * characters[randomSelectedType].length)];
                password += randomChar;
            }

            return password;
        },
        formatXml:function (xmlStr){
            //计算头函数	用来缩进
            function setPrefix(prefixIndex) {
                var result = '';
                var span = '    ';//缩进长度
                var output = [];
                for (var i = 0; i < prefixIndex; ++i) {
                    output.push(span);
                }
                result = output.join('');
                return result;
            }

            let text = xmlStr;
            //使用replace去空格
            text = '\n' + text.replace(/(<\w+)(\s.*?>)/g, function ($0, name, props) {
                return name + ' ' + props.replace(/\s+(\w+=)/g, " $1");
            }).replace(/>\s*?</g, ">\n<");
            //处理注释
            text = text.replace(/\n/g, '\r').replace(/<!--(.+?)-->/g, function ($0, text) {
                var ret = '<!--' + escape(text) + '-->';
                return ret;
            }).replace(/\r/g, '\n');
            //调整格式	以压栈方式递归调整缩进
            var rgx = /\n(<(([^\?]).+?)(?:\s|\s*?>|\s*?(\/)>)(?:.*?(?:(?:(\/)>)|(?:<(\/)\2>)))?)/mg;
            var nodeStack = [];
            var output = text.replace(rgx, function ($0, all, name, isBegin, isCloseFull1, isCloseFull2, isFull1, isFull2) {
                var isClosed = (isCloseFull1 == '/') || (isCloseFull2 == '/') || (isFull1 == '/') || (isFull2 == '/');
                var prefix = '';
                if (isBegin == '!') {//!开头
                    prefix = setPrefix(nodeStack.length);
                } else {
                    if (isBegin != '/') {///开头
                        prefix = setPrefix(nodeStack.length);
                        if (!isClosed) {//非关闭标签
                            nodeStack.push(name);
                        }
                    } else {
                        nodeStack.pop();//弹栈
                        prefix = setPrefix(nodeStack.length);
                    }
                }
                var ret = '\n' + prefix + all;
                return ret;
            });
            var prefixSpace = -1;
            var outputText = output.substring(1);
            //还原注释内容
            outputText = outputText.replace(/\n/g, '\r').replace(/(\s*)<!--(.+?)-->/g, function ($0, prefix, text) {
                if (prefix.charAt(0) == '\r')
                    prefix = prefix.substring(1);
                text = unescape(text).replace(/\r/g, '\n');
                var ret = '\n' + prefix + '<!--' + text.replace(/^\s*/mg, prefix) + '-->';
                return ret;
            });
            outputText = outputText.replace(/\s+$/g, '').replace(/\r/g, '\r\n');
            return outputText;
        }
    },
    loadscripts: function (scripts, callback) {
        var index = 0;

        function next() {
            if (index < scripts.length) {
                layui.$.getScript(system_config.basePath + scripts[index])
                    .done(function (script, textstatus) {
                        console.log(textstatus + ":" + scripts[index]);
                        index++;
                        next();
                    })
                    .fail(function (jqxhr, script, exception) {
                        console.log(jqxhr,script,exception)
                        console.log("加载失败:" + scripts[index]);
                    })
            } else {
                callback();
            }
        }

        next();
    }
}
//全局配置
top.config = {
    constant: {
        token: "Access-Token",
        sm2:{
            publicKey: "04e785147677f0172fbc31d1cff578affdf4607c36bf16e81621f055c48d4f5c7340fe314c55883af35062dbe42c77b1aed66a858679eaad7f67963fc51b2e2593",
            privateKey: "d10f66151883dc86e2d381db8fc108b452bcc50f8bcf98334d3eb31745ee698c"
        },
        sm3:'daac25c1512fe50f79b0e4526b93f5c0e1460cef40b6dd44af13caec62e8c60e0d885f3c6d6fb51e530889e6fd4ac743a6d332e68a0f2a3923f42585dceb93e9',
        sm4:{
            key:'0123456789abcdeffedcba9876543210',
            iv:'fedcba98765432100123456789abcdef'
        }
    },
    //主题配置
    theme: {
        //内置主题配色方案
        color: [{
            main: '#20222A' //主题色
            , selected: '#009688' //选中色
            , alias: '默认' //默认别名
        }, {
            main: '#03152A'
            , selected: '#3B91FF'
            , alias: '藏蓝' //藏蓝
        }, {
            main: '#2E241B'
            , selected: '#A48566'
            , alias: '咖啡' //咖啡
        }, {
            main: '#50314F'
            , selected: '#7A4D7B'
            , alias: '紫红' //紫红
        }, {
            main: '#344058'
            , logo: '#1E9FFF'
            , selected: '#1E9FFF'
            , alias: '海洋' //海洋
        }, {
            main: '#3A3D49'
            , logo: '#2F9688'
            , selected: '#5FB878'
            , alias: '墨绿' //墨绿
        }, {
            main: '#20222A'
            , logo: '#F78400'
            , selected: '#F78400'
            , alias: '橙色' //橙色
        }, {
            main: '#28333E'
            , logo: '#AA3130'
            , selected: '#AA3130'
            , alias: '时尚红' //时尚红
        }, {
            main: '#24262F'
            , logo: '#3A3D49'
            , selected: '#009688'
            , alias: '经典黑' //经典黑
        }, {
            logo: '#226A62'
            , header: '#2F9688'
            , alias: '墨绿头' //墨绿头
        }, {
            main: '#344058'
            , logo: '#0085E8'
            , selected: '#1E9FFF'
            , header: '#1E9FFF'
            , alias: '海洋头' //海洋头
        }, {
            header: '#393D49'
            , alias: '经典黑' //经典黑
        }, {
            main: '#50314F'
            , logo: '#50314F'
            , selected: '#7A4D7B'
            , header: '#50314F'
            , alias: '紫红头' //紫红头
        }, {
            main: '#28333E'
            , logo: '#28333E'
            , selected: '#AA3130'
            , header: '#AA3130'
            , alias: '时尚红头' //时尚红头
        }, {
            main: '#28333E'
            , logo: '#009688'
            , selected: '#009688'
            , header: '#009688'
            , alias: '墨绿头' //墨绿头
        }]
        //初始的颜色索引，对应上面的配色方案数组索引
        //如果本地已经有主题色记录，则以本地记录为优先，除非请求本地数据（localStorage）
        , initColorIndex: 0
    }
}